package com.sprite.utils;


import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

/**
 * 字符串处理工具类
 *
 * @author Jack
 */
public final class UtilString {
    private UtilString() {
    }

    /**
     * <p>字符串是否为空, "" or null</p>
     *
     * @param cs
     *         字符序列
     * @return 结果
     */
    public static boolean isEmpty(CharSequence cs) {
        return cs == null || cs.length() == 0;
    }

    /**
     * @param cs
     *         字符序列
     * @return 判断结果
     */
    public static boolean isNotEmpty(CharSequence cs) {
        return !isEmpty(cs);
    }

    /**
     * <p>检查字符序列是否为空, " or null.</p>
     * <p>
     * StringUtils.isBlank(null)      = true
     * StringUtils.isBlank("")        = true
     * StringUtils.isBlank(" ")       = true
     * StringUtils.isBlank("bob")     = false
     * StringUtils.isBlank("  bob  ") = false
     *
     * @param cs
     *         字符序列
     * @return 判断结果
     */
    public static boolean isBlank(CharSequence cs) {
        int strLen;
        if (cs == null || (strLen = cs.length()) == 0) {
            return true;
        }

        for (int i = 0; i < strLen; i++) {
            if (Character.isWhitespace(cs.charAt(i)) == false) {
                return false;
            }
        }
        return true;
    }

    /**
     * <p>Checks if a CharSequence is not empty (""), not null and not whitespace only.</p>
     * <p>
     * StringUtils.isNotBlank(null)      = false
     * StringUtils.isNotBlank("")        = false
     * StringUtils.isNotBlank(" ")       = false
     * StringUtils.isNotBlank("bob")     = true
     * StringUtils.isNotBlank("  bob  ") = true
     * </p>
     *
     * @param cs
     *         字符序列
     * @return 判断结果
     */
    public static boolean isNotBlank(CharSequence cs) {
        return !isBlank(cs);
    }

    public static String toString(Object obj) {
        return toString(obj, null);
    }

    public static String toString(Object obj, String defaultValue) {
        if (obj == null) {
            return defaultValue;
        } else {
            return String.valueOf(obj);
        }
    }

    /**
     * @param str
     *         字符串
     * @param delimiter
     *         分割辞
     * @return 字符数组
     */
    public static String[] tokenizeToStringArray(String str, String delimiter) {
        if (delimiter == null) {
            return new String[]{str};
        }

        List<String> result = tokenizeToStringList(str, delimiter);
        return result.toArray(new String[result.size()]);
    }

    /**
     * CSV
     *
     * @param str
     *         要分割的字符
     * @return 字符数组
     */
    public static String[] commaDelimiteToStringArray(String str) {
        return tokenizeToStringArray(str, ",");
    }

    /**
     * @param str
     *         字符串
     * @param delimiter
     *         分割辞
     * @return 字符集合
     */
    public static List<String> tokenizeToStringList(String str, String delimiter) {
        if (str == null) {
            return Collections.emptyList();
        }

        List<String> result = new LinkedList<String>();
        int delimiterLength = delimiter.length();

        int pos = 0;
        int delPos;
        while ((delPos = str.indexOf(delimiter, pos)) != -1) {
            result.add(str.substring(pos, delPos));
            pos = delPos + delimiterLength;
        }

        if (pos < str.length()) {
            result.add(str.substring(pos));
        }

        if (result.isEmpty()) {
            result.add(str);
        }
        return result;
    }

    /**
     * CSV
     *
     * @param str
     *         要分割的字符
     * @return 字符集合
     */
    public static List<String> commaDelimiteToStringList(String str) {
        return tokenizeToStringList(str, ",");
    }

    public static String join(Collection<String> strs, String delimiter) {
        StringBuilder stringBuilder = new StringBuilder();

        if (UtilCollection.isNotEmpty(strs)) {
            for (String str : strs) {
                stringBuilder.append(str).append(delimiter);
            }

            stringBuilder.delete(stringBuilder.length() - delimiter.length(), stringBuilder.length());
        }

        return stringBuilder.toString();
    }

    public static String joinToCSV(Collection<String> strs) {
        return join(strs, ",");
    }

    /**
     * @param strs
     *         字符串数组
     * @return csv
     * @since 1.2.6
     */
    public static String joinToCSV(String[] strs) {
        return join(strs, ",");
    }

    /**
     * @param objects
     *         多个对象
     * @return csv
     * @since 1.2.7
     */
    public static String joinToCSV(Object[] objects) {
        return join(objects, ",");
    }

    /**
     * @param strs
     *         字符串数组
     * @param delimiter
     *         分隔符
     * @return 字符
     * @since 1.2.6
     */
    public static String join(String[] strs, String delimiter) {
        StringBuilder stringBuilder = new StringBuilder();

        if (UtilArray.isEmpty(strs)) {
            for (String str : strs) {
                stringBuilder.append(str).append(delimiter);
            }

            stringBuilder.delete(stringBuilder.length() - delimiter.length(), stringBuilder.length());
        }

        return stringBuilder.toString();
    }

    /**
     * 连接成字符串，调用每个对象的 String.valueOf()
     *
     * @param objs
     * @param delimiter
     *         分割符
     * @return
     * @see String#valueOf(Object)
     * @since 1.2.7
     */
    public static String join(Object[] objs, String delimiter) {
        StringBuilder stringBuilder = new StringBuilder();

        if (UtilArray.isEmpty(objs)) {
            for (Object str : objs) {
                stringBuilder.append(str).append(delimiter);
            }

            stringBuilder.delete(stringBuilder.length() - delimiter.length(), stringBuilder.length());
        }

        return stringBuilder.toString();
    }

    /**
     * 占位符替换，占位符 "{n}" 或“{}”
     * <p>n从0开始，假如没有指定n，则n的值为当前站位符的索引</p>
     *
     * @param str
     *         字符
     * @param params
     *         替换参数
     * @return 格式化后的字符序列
     */
    public static String place(String str, Object... params) {
        if (params == null || params.length == 0) return str;

        StringBuilder stringBuilder = new StringBuilder();

        char[] chs = str.toCharArray();

        int pi = 0; // 下标，从左至右，从0开始

        int index; // 下标，表明是第几个参数
        int indexStart = 0;
        int offset = 0;
        boolean isIndex = false;    // 是否开始获取下标

        int i = -1;   // 字符索引
        for (char ch : chs) {
            i++;
            if (!isIndex) {
                if (ch == '{') {
                    isIndex = true;
                    indexStart = i + 1;// 不包含开始字符
                    offset = 0;
                } else {
                    stringBuilder.append(ch);
                }
            }

            if (isIndex) {
                if (ch != '{') {// 偏移量右移
                    offset++;
                }

                if (ch == '}') {// 下标获取结束
                    offset--;// 不包含结束字符
                    index = UtilMisc.castToInt(new String(chs, indexStart, offset), pi);
                    if (index >= params.length || index < 0) {
                        stringBuilder.append(chs, indexStart - 1, offset + 2);
                    } else {
                        stringBuilder.append(params[index].toString());
                    }
                    isIndex = false;
                    pi++;
                }
            }
        }

        return stringBuilder.toString();
    }

    private static final char[] hexChars = {
            '0', '1', '2', '3', '4', '5',
            '6', '7', '8', '9', 'A', 'B',
            'C', 'D', 'E', 'F'
    };

    /**
     * 字节数组转换成16进制字符
     *
     * @param data
     *         字节数组
     * @return 16进制字符
     */
    public static String byteToHex(byte[] data) {
        if (null == data || data.length <= 0) {
            return "";
        }

        StringBuilder buffer = new StringBuilder();
        for (int b : data) {
            b &= 0xFF;
            buffer.append(hexChars[b >>> 4]);
            buffer.append(hexChars[b & 0x0F]);
        }
        return buffer.toString();
    }


    /**
     * 十六进制字符串转byte数组
     *
     * @param hexString
     *         十六进制字符串
     * @return 字节数组
     */
    public static byte[] hexStringToBytes(String hexString) {
        if (isEmpty(hexString)) {
            return null;
        }
        if (hexString.length() % 2 != 0) {
            throw new IllegalArgumentException("");
        }

        char[] chars = hexString.toCharArray();

        byte[] bts = new byte[hexString.length() / 2];
        for (int i = 0; i < bts.length; i++) {
            bts[i] = (byte) (hexCharToDec(chars[i << 1]) << 4 | hexCharToDec(chars[(i << 1) + 1]));
        }

        return bts;
    }

    /**
     * 16进制字符转为十进制
     *
     * @param ch
     *         字符
     * @return 16进制
     */
    private static int hexCharToDec(char ch) {
        if (ch <= 70) {
            return "0123456789ABCDEF".indexOf(ch);
        } else {
            return "0123456789ABCDEF".indexOf(ch - 35);
        }
    }
}

